package Export_module

import (
	"dba_toolbox/Global"
	"fmt"
	"os"
	"strconv"
	"strings"
	"sync"
	"time"

	"github.com/chzyer/readline"
)

func Export_sql() {
	fmt.Println("欢迎使用DBA_TOOLBOX的数据导出SQL功能")
	rl, err := readline.New("请输入要导出的表_格式[库名.表名]_例:test.tb_test> ")
	if err != nil {
		panic(err)
	}
	defer rl.Close()

	tableName, err := rl.Readline()

	if err != nil {
		panic(err)
	}

	r2, err := readline.New("请选择并发线程数(默认10线程)> ")
	if err != nil {
		panic(err)
	}
	defer rl.Close()

	threadsStr, err := r2.Readline()

	if err != nil {
		panic(err)
	}
	threads, _ := strconv.Atoi(threadsStr) //并发协程数，可以根据实际情况调整

	start_Time := time.Now()
	err = exportTableToSQL(tableName, threads)
	if err != nil {
		fmt.Println("导出数据失败：", err)
		return
	}
	//获取结束时间
	end_Time := time.Now()
	//计算两时间相差
	elapsed_time := end_Time.Sub(start_Time)
	//输出总耗时
	fmt.Println("导出总耗时：", elapsed_time)
}

func getTableStructure(tableName string) (string, error) {
	var structure string
	query := fmt.Sprintf("SHOW CREATE TABLE %s", tableName)
	err := Global.DB.QueryRow(query).Scan(&tableName, &structure)
	if err != nil {
		return "", err
	}
	return structure, nil
}
func getTotalRowCount(tableName string) (int, error) {
	var structure int
	query := fmt.Sprintf("SELECT COUNT(*) FROM %s", tableName)
	err := Global.DB.QueryRow(query).Scan(&structure)
	if err != nil {
		return 0, err
	}
	return structure, nil
}

func getTableData(tableName string, start, end int) ([]string, error) {
	var rows []string

	query := fmt.Sprintf("SELECT * FROM %s LIMIT %d, %d", tableName, start, end)
	result, err := Global.DB.Query(query)
	if err != nil {
		return rows, err
	}
	defer result.Close()

	columns, err := result.Columns()
	if err != nil {
		return rows, err
	}

	values := make([]interface{}, len(columns))
	scanArgs := make([]interface{}, len(columns))
	for i := range values {
		scanArgs[i] = &values[i]
	}

	for result.Next() {
		if err := result.Scan(scanArgs...); err != nil {
			return rows, err
		}

		var rowValues []string
		for _, value := range values {
			if value == nil {
				rowValues = append(rowValues, "NULL")
			} else {
				rowValues = append(rowValues, fmt.Sprintf("`%s`", value))
			}
		}
		rows = append(rows, "("+strings.Join(rowValues, ", ")+")")
	}

	return rows, nil
}
func exportToSQLFile(tableName, tableStructure string, tableData []string) error {
	fileName := tableName + ".sql"
	file, err := os.Create(fileName)
	if err != nil {
		return err
	}
	defer file.Close()

	_, err = file.WriteString(tableStructure + ";\n\n")
	if err != nil {
		return err
	}

	_, err = file.WriteString("INSERT INTO " + tableName + " VALUES\n")
	if err != nil {
		return err
	}

	for i, row := range tableData {
		_, err := file.WriteString(row)
		if err != nil {
			return err
		}

		if i != len(tableData)-1 {
			_, err = file.WriteString(",\n")
			if err != nil {
				return err
			}
		}
	}

	_, err = file.WriteString(";\n")
	if err != nil {
		return err
	}

	fmt.Println("导出成功，文件名为：", fileName)
	return nil
}
func exportTableToSQL(tableName string, concurrency int) error {
	tableStructure, err := getTableStructure(tableName)
	if err != nil {
		return err
	}

	totalRows, err := getTotalRowCount(tableName)
	if err != nil {
		return err
	}

	rowsPerRoutine := totalRows / concurrency //长度
	remainder := totalRows % concurrency      //余数

	var wg sync.WaitGroup
	wg.Add(concurrency)

	var tableData []string

	for i := 0; i < concurrency; i++ {
		startRow := i * rowsPerRoutine
		endRow := rowsPerRoutine
		if i == concurrency-1 {
			endRow += remainder
		}

		go func(start, end int) {
			defer wg.Done()

			data, err := getTableData(tableName, start, end)
			if err != nil {
				fmt.Println(err)
				return
			}

			tableData = append(tableData, data...)
		}(startRow, endRow)
	}

	wg.Wait()

	err = exportToSQLFile(tableName, tableStructure, tableData)
	if err != nil {
		return err
	}

	return nil
}
